package com.hg.design.structure.flyweight.biancheng.ex2;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

//棋盘
public class Chessboard extends MouseAdapter {
    WeiqiFactory wf;
    JFrame f;
    Graphics g;
    JRadioButton wz;
    JRadioButton bz;
    JPanel centerJP;
    private final int x = 50;
    private final int y = 50;
    private final int w = 40;    //小方格宽度和高度
    private final int rw = 400;    //棋盘宽度和高度
    String[][] chessSizeAndColor = new String[11][11];
    Chessboard() {
        wf = new WeiqiFactory();
//        f = new JFrame("享元模式在五子棋游戏中的应用");
        f = new JFrame("五子棋");
        f.setBounds(100, 100, 500, 550);
        f.setVisible(true);
        f.setResizable(false);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel southJP = new JPanel();
        f.add("South", southJP);
        wz = new JRadioButton("白子");
        bz = new JRadioButton("黑子", true);
        ButtonGroup group = new ButtonGroup();
        group.add(wz);
        group.add(bz);
        southJP.add(wz);
        southJP.add(bz);
        this.centerJP = new JPanel();
        this.centerJP.setLayout(null);
        this.centerJP.setSize(500, 500);
        this.centerJP.addMouseListener(this);
        f.add("Center", this.centerJP);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        g = this.centerJP.getGraphics();
        g.setColor(Color.BLUE);
        g.drawRect(x, y, rw, rw);
        for (int i = 1; i < 10; i++) {
            //绘制第i条竖直线
            g.drawLine(x + (i * w), y, x + (i * w), y + rw);
            //绘制第i条水平线
            g.drawLine(x, y + (i * w), x + rw, y + (i * w));
        }
    }

    public void mouseClicked(MouseEvent e) {
        if (e.getX() < 35 || e.getX() > 465 || e.getY() < 35 || e.getY() > 465) {
            JOptionPane.showMessageDialog(null, "落棋位置错误!","温馨提示",JOptionPane.INFORMATION_MESSAGE);
        } else {
//            Point pt = new Point(e.getX() - 15, e.getY() - 15);
            //坐标精确
            int x = Math.round((float)(e.getX() - 50) / 40);
            int y = Math.round((float)(e.getY() - 50) / 40);
            Point pt = new Point(x * 40 + 35, y * 40 + 35);

            //判断是否已有棋子
            if (chessSizeAndColor[x][y] == null) {
                if (wz.isSelected()) {
                    ChessPieces c1 = wf.getChessPieces("w");
                    c1.DownPieces(g, pt);
                    chessSizeAndColor[x][y] = "w";

                    //判断是否连成五子
                    if(isWin(x, y, "w")) {
                        this.centerJP.removeMouseListener(this);
                        JOptionPane.showMessageDialog(null, "恭喜白棋获胜!","胜利",JOptionPane.INFORMATION_MESSAGE);
                    } else {
                        //切换棋色
                        wz.setSelected(false);
                        bz.setSelected(true);
                    }
                } else if (bz.isSelected()) {
                    ChessPieces c2 = wf.getChessPieces("b");
                    c2.DownPieces(g, pt);
                    chessSizeAndColor[x][y] = "b";

                    //判断是否连成五子
                    if(isWin(x, y, "b")) {
                        this.centerJP.removeMouseListener(this);
                        JOptionPane.showMessageDialog(null, "恭喜黑棋获胜!","胜利",JOptionPane.INFORMATION_MESSAGE);
                    } else {
                        //切换棋色
                        bz.setSelected(false);
                        wz.setSelected(true);
                    }
                }
            } else {
                JOptionPane.showMessageDialog(null, "此位置已有棋子!","温馨提示",JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }

    //判断输赢
    private boolean isWin(int x, int y, String color) {
        CompletableFuture<Boolean> abscissa = CompletableFuture.supplyAsync(() -> this.abscissaJudgment(x, y, color));
        CompletableFuture<Boolean> ordinate = CompletableFuture.supplyAsync(() -> this.ordinateJudgment(x, y, color));
        CompletableFuture<Boolean> oneThree = CompletableFuture.supplyAsync(() -> this.oneThreeJudgment(x, y, color));
        CompletableFuture<Boolean> twoFour = CompletableFuture.supplyAsync(() -> this.twoFourJudgment(x, y, color));
        CompletableFuture.allOf(abscissa, ordinate, oneThree, twoFour).join();
        try {
            if (abscissa.get() || ordinate.get() || oneThree.get() || twoFour.get()) {
                return true;
            }
        } catch (InterruptedException e) {
            System.out.println("胜利判断方法执行异常：" + e.getMessage());
            e.printStackTrace();
            return false;
        } catch (ExecutionException e) {
            System.out.println("胜利判断方法执行异常：" + e.getMessage());
            e.printStackTrace();
            return false;
        }

        return false;
    }

    //横坐标判断
    private boolean abscissaJudgment(int x, int y, String color){
        int num = 1;
        num = leftCount(num, x-1, y, color);
        num = rightCount(num, x+1, y, color);
        return num > 4;
    }

    //纵坐标判断
    private boolean ordinateJudgment(int x, int y, String color){
        int num = 1;
        num = upCount(num, x, y-1, color);
        num = downCount(num, x, y+1, color);
        return num > 4;
    }

    //一三象限判断
    private boolean oneThreeJudgment(int x, int y, String color){
        int num = 1;
        num = rightUpCount(num, x+1, y-1, color);
        num = leftDownCount(num, x-1, y+1, color);
        return num > 4;
    }

    //二四象限判断
    private boolean twoFourJudgment(int x, int y, String color){
        int num = 1;
        num = leftUpCount(num, x-1, y-1, color);
        num = rightDownCount(num, x+1, y+1, color);
        return num > 4;
    }

    //向左计数Judgment
    private int leftCount(int num, int x, int y, String color) {
        if (x >= 0 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return leftCount(num, x-1, y, color);
        } else {
            return num;
        }
    }

    //向右计数
    private int rightCount(int num, int x, int y, String color) {
        if (x <= 11 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return rightCount(num, x+1, y, color);
        } else {
            return num;
        }
    }

    //向上计数Judgment
    private int upCount(int num, int x, int y, String color) {
        if (y >= 0 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return upCount(num, x, y-1, color);
        } else {
            return num;
        }
    }

    //向下计数Judgment
    private int downCount(int num, int x, int y, String color) {
        if (y <= 11 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return downCount(num, x, y+1, color);
        } else {
            return num;
        }
    }

    //向左上计数Judgment
    private int leftUpCount(int num, int x, int y, String color) {
        if (x >= 0 && y >= 0 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return leftUpCount(num, x-1, y-1, color);
        } else {
            return num;
        }
    }

    //向右下计数
    private int rightDownCount(int num, int x, int y, String color) {
        if (x <= 11 && y <= 11 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return rightDownCount(num, x+1, y+1, color);
        } else {
            return num;
        }
    }

    //向左下计数Judgment
    private int leftDownCount(int num, int x, int y, String color) {
        if (x >= 0 && y <= 11 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return leftDownCount(num, x-1, y+1, color);
        } else {
            return num;
        }
    }

    //向右上计数
    private int rightUpCount(int num, int x, int y, String color) {
        if (x <= 11 && y >= 0 && chessSizeAndColor[x][y] != null && chessSizeAndColor[x][y].equals(color)) {
            num += 1;
            return rightUpCount(num, x+1, y-1, color);
        } else {
            return num;
        }
    }
}
